package cn.gwm.flink.streaming.strategy.cloudpredict;

import cn.gwm.flink.streaming.constant.ChargePredictFields;
import cn.gwm.flink.streaming.strategy.vehiclepredict.DwsStrConstant;
import cn.gwm.utils.HBaseDataSource;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.flink.api.common.state.MapState;

import java.io.Serializable;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.*;

/**
 * @author : GW00280745
 * @date : 2023/5/11 8:06
 * @description : 云端预测 工况匹配
 */
public class CloudMatch implements Serializable {
    private CloudDefaultVal cloudDefaultVal = new CloudDefaultVal();
    public void process(JSONObject line, boolean isUpdatePhase,
                        MapState<String, String> initState
                        ,MapState<String, String> latestEstimateState
                        ,MapState<String, String> timeOfLatest5State
                        ,MapState<String, String> startSocState
    ){
        try {
            //0. 添加字段 -- 处理时间
            String format = DateFormatUtils.format(System.currentTimeMillis(), ChargePredictFields.ins().yyyyMmddss1);
            line.put(ChargePredictFields.ins().handleTime,format);
            //1. 数据加工处理
            String predict = predict(line, isUpdatePhase, initState,timeOfLatest5State,startSocState);
            //2. 结果校验
            dataState(line,predict,latestEstimateState);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 状态处理-- 加工结果写道状态中
     *
     *
     * @param line
     * @param predictStr
     */
    private void dataState(JSONObject line, String predictStr
            ,MapState<String, String> latestEstimateState) {
        try {
            if (StringUtils.isBlank(predictStr)){
                return;
            }
            String chargeId = chargeIdName(line);
            boolean isStageChange = stageChange(line, latestEstimateState, chargeId);
            //结果校验
            String predict = checkPredictResult(line,predictStr,latestEstimateState,isStageChange);
            //解析计算结果
            String[] split = predict.split(ChargePredictFields.ins().char3);
            String estimateTime = split[2];

            //添加字段--predict_time字段   原本格式= 2022-09-10 17:05:22  临时用它存储每次预测的过程
//            String predictTime = predictTime(line, estimateTime)
            String predictTime = estimateTime;
            String keyPredict = ChargePredictFields.ins().stdFieldPredictTime;
            String stateKeyPredict = chargeId.concat(keyPredict);
            line.put(keyPredict, predictTime);
            latestEstimateState.put(stateKeyPredict, predictTime);

            //添加字段-- predict_time_multidimension
            String keyMult = ChargePredictFields.ins().stdFieldPredictTimeV2;
            String stateKeyMult = chargeId.concat(keyMult);
            line.put(keyMult, predict);
            latestEstimateState.put(stateKeyMult, predict);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    private boolean stageChange(JSONObject line, MapState<String, String> latestEstimateState, String chargeId) throws Exception {
        String stateKey = chargeId.concat("policyType");
        String policyType = line.getString("policyType");
        String policyTypeState = latestEstimateState.get(stateKey);
        if (StringUtils.isBlank(policyTypeState)){
            latestEstimateState.put(stateKey,policyType);
            return false;
        }
        //阶段切换点不做校验
        boolean b = !StringUtils.equalsIgnoreCase(policyTypeState, "update-jisuan");
        boolean c = StringUtils.equalsIgnoreCase(policyType, "update-jisuan");
        latestEstimateState.put(stateKey,policyType);
        //上一个状态不是更新 当前状态是更新
        if (b && c){
            return true;
        }
        return false;
    }

    /**
     *  每一个结果，需要和前面的结果进行比对
     *  产生大上次的结果，沿用上次的结果
     *  当连续3次（TBD）的计算结果，均大于前面的计算结果、或充电电流减少到原电流的70%以下，方可将新结果进行显示下发。
     * @param line
     * @param predictStr
     * @return
     */
    private String checkPredictResult(JSONObject line, String predictStr,MapState<String, String> latestEstimateState,boolean isStageChange) {
        try {
            String chargeId = chargeIdName(line);
            String curr = line.getString(ChargePredictFields.ins().srcFieldBmsBatterCurrRm);
            String stateKey = chargeId.concat("predict");
            String stateVal = latestEstimateState.get(stateKey);
            String tidVal = line.getString(ChargePredictFields.ins().srcFieldTid);
            if (StringUtils.isBlank(stateVal)){
                String concat = predictStr
                        .concat(ChargePredictFields.ins().char3).concat("0")
                        .concat(ChargePredictFields.ins().char3).concat(curr)
                        ;
                latestEstimateState.put(stateKey,concat);
                return predictStr;
            }
            if (isStageChange){
                String concat = predictStr
                        .concat(ChargePredictFields.ins().char3).concat("0")
                        .concat(ChargePredictFields.ins().char3).concat(curr)
                        ;
                latestEstimateState.put(stateKey,concat);
                return predictStr;
            }
            //有之前的结果 则进行判断 只要小于
            String[] stateSp = stateVal.split(ChargePredictFields.ins().char3);
            Float stateTime = Float.parseFloat(stateSp[2]);

            String[] sp = predictStr.split(ChargePredictFields.ins().char3);
            Float time = Float.parseFloat(sp[2]);
            if (time>stateTime){
                //如果时间大于之前的计算结果则返回之前的结果
                String cntStr = stateSp[3];
                int i = Integer.parseInt(cntStr);
                String currStateStr = stateSp[4];
                float currStateF = Float.parseFloat(currStateStr);
                float currF = Float.parseFloat(curr);
                float v = Math.abs((currStateF - currF)/currStateF);
                //充电电流减少到原电流的70%以下
                boolean currB = currStateF < currF && v >= 0.7;
                boolean cntB = i >= DwsStrConstant.ins().num3;
                if ( !(cntB || currB) ){
                    //返回上一次的结果
                    //将上一次的结果的次数加1
                    String concat = stateSp[0].concat(ChargePredictFields.ins().char3)
                            .concat(stateSp[1]).concat(ChargePredictFields.ins().char3)
                            .concat(stateSp[2]).concat(ChargePredictFields.ins().char3)
                            .concat(String.valueOf(i + 1)).concat(ChargePredictFields.ins().char3)
                            .concat(stateSp[4]).concat(ChargePredictFields.ins().char3);
                    latestEstimateState.put(stateKey,concat);
                    return stateVal;
                }
            }
            //如果小于 则更新状态并返回
            String concat = predictStr.concat(ChargePredictFields.ins().char3).concat("0")
                    .concat(ChargePredictFields.ins().char3).concat(curr);
            latestEstimateState.put(stateKey,concat);
            return predictStr;
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

    public String predictTime(JSONObject line, String deltaTime) {
        try {
            //预测时间单位=min
            long estiTime = new BigDecimal(deltaTime).longValue();
            long l = estiTime * 60 * 1000L;
            Long tid = line.getLong(ChargePredictFields.ins().srcFieldTid);
            long ls = tid + l;
            String format = DateFormatUtils.format(ls, ChargePredictFields.ins().yyyyMmddss1);
            return format;
        }catch (Exception e){
            return ChargePredictFields.ins().blankStr9;
        }
    }
    /**
     *  工况匹配 加工逻辑
     *
     * @param line
     */

    public String predict(JSONObject line, boolean isUpdatePhase
            , MapState<String, String> initState
            , MapState<String, String> timeOfLatest5State
            ,MapState<String, String> startSocState
    ){
        if (isUpdatePhase){
            //更新计算
            String res= calOfUpdate(line,timeOfLatest5State,startSocState,initState);
            if (StringUtils.isBlank(res)){
                res = "0#0#-999999";
            }
            return res;
        }
        //初始计算
        String res= calOfFirst(line,initState);
        if (StringUtils.isBlank(res)){
            //调用更新计算
            res= calOfUpdateFirstIsNull(line,timeOfLatest5State,startSocState,initState);
        }
        if (StringUtils.isBlank(res)){
            res = "0#0#-999999";
        }
        return res;
    }

    /**
     * 更新计算
     * @param line
     * @return
     */
    private String calOfUpdate(JSONObject line
            , MapState<String, String> timeOfLatest5State
            ,MapState<String, String> startSocState
            ,MapState<String, String> initState
    ) {
        line.put("policyType","update-jisuan");
        String obc = line.getString(ChargePredictFields.ins().srcFieldBmsObcConnect);
        String dc = line.getString(ChargePredictFields.ins().srcFieldBmsDcConnect);
        if (StringUtils.equalsIgnoreCase(obc,DwsStrConstant.ins().str1)){
            //慢充
            return calOfUpdateObc(line,timeOfLatest5State,startSocState,initState);
        }else if (StringUtils.equalsIgnoreCase(dc,DwsStrConstant.ins().str1)){
            //快充
            return calOfUpdateDc(line,timeOfLatest5State,startSocState,initState);
        }
        return null;
    }

    private String calOfUpdateObc(JSONObject line, MapState<String, String> timeOfLatest5State, MapState<String, String> startSocState, MapState<String, String> initState) {
        try {
            String chargeIdName = chargeIdName(line);
            //obc 慢充 更新阶段使用 最近5个点的平均值
            float startSocVal = getStartSocVal(line, startSocState);
            Float bmsSoc = line.getFloat(ChargePredictFields.ins().srcFieldBmsSoc);
            //先看有没有前几个点的记录
            String s = timeOfLatest5State.get(chargeIdName);
            if (StringUtils.isBlank(s)){
                //没有前几个点数据 不处理
                return null;
            }
            //获取前5个点的充电时长
            float sliceTime = sliceTimeOfLatest5Record(line,timeOfLatest5State);
            float sliceTimeSrc = sliceTime;
            sliceTime= curr2SliceTime(line,sliceTime);
            float deltaSoc = 100 - bmsSoc;
            BigDecimal totalTime = new BigDecimal(sliceTime).multiply(new BigDecimal(deltaSoc));
            int i0 = totalTime.divide(new BigDecimal(60000), 0, BigDecimal.ROUND_HALF_DOWN).intValue();
            int i = i0;
            if (i>DwsStrConstant.ins().timeLim){
                i = DwsStrConstant.ins().timeLim;
            }
            String concat = bmsSoc.toString().concat(ChargePredictFields.ins().char3).concat("100").concat(ChargePredictFields.ins().char3).concat(String.valueOf(i));
            System.out.println(String.format("chargeId=%s,update obc ---> time(sliceTime * (100 - bms_innersoc) )=%s,sliceTime=%s(%s),bms_innersoc=%s",chargeIdName,i0,sliceTime,sliceTimeSrc,bmsSoc));
            return concat;
        }catch (Exception e){
            e.printStackTrace();
        }

        return null;
    }
    private Float curr2SliceTime(JSONObject line,float time){
//        try {
//            Float bmsCurr = line.getFloat(ChargePredictFields.ins().srcFieldBmsBatterCurrRm);
//            float abs = Math.abs(bmsCurr);
//            //如果电流小于8A 则平均时间应该在
//            if(abs <= 8){
//                if (time<600000){
//                    return  780000f;
//                }else if(time > 800000){
//                    return  780000f;
//                }
//            }else if ( abs>=8.9 && abs <= 10){
//                // 时间应该在9分钟 大概540s 上下加减100s
//                if (time <400000){
//                    return 540000f;
//                }else if (time > 700000){
//                    return 540000f;
//                }
//            }else if ( abs>=17 && abs <= 18){
//                // 时间应该在5分钟 大概300s 上下加减100s
//                if (time <100000){
//                    return 300000f;
//                }else if (time > 500000){
//                    return 300000f;
//                }
//            }
//        }catch (Exception e){
//            e.printStackTrace();
//        }
        return time;
    }
    private String calOfUpdateDc(JSONObject line, MapState<String, String> timeOfLatest5State, MapState<String, String> startSocState, MapState<String, String> initState) {
        try {
            //dc 快充
            float startSocVal = getStartSocVal(line, startSocState);
            //先看有没有前几个点的记录
            String chargeIdName = chargeIdName(line);
            String s = timeOfLatest5State.get(chargeIdName);
            if (StringUtils.isBlank(s)){
                //没有前几个点数据 不处理
                return null;
            }
            //获取前5个点的充电时长
            float sliceTime = sliceTimeOfLatest5Record(line,timeOfLatest5State);
            //分段计算 1-温度调节 2-高效 3-涓流
            float time1 = stageOfTempAdjust(line,sliceTime,startSocVal);
            float time2 = stageOfEfficient(line,sliceTime,startSocVal,initState);
            float time3 = stageOfTrickle(line,sliceTime,startSocVal,initState);
            //END.结果计算
            float totalTime = time1 + time2 + time3 ;
            int i = new BigDecimal(totalTime).divide(new BigDecimal(60000), 0, BigDecimal.ROUND_HALF_DOWN).intValue();
            String bmsSoc = line.getString(ChargePredictFields.ins().srcFieldBmsSoc);
            System.out.println(String.format("chargeId=%s,update ---> time(stage1+stage2+stage3)=%s,startsoc=%s,bms_innersoc=%s,sliceTime=%s,stage1=%s,stage2=%s,stage3=%s",chargeIdName,i,startSocVal,bmsSoc,sliceTime,time1,time2,time3));
            String socEnd = line.getString(steadySocEndKey);
            if (StringUtils.isBlank(socEnd)){
                socEnd ="100";
            }
            String concat = bmsSoc.concat(ChargePredictFields.ins().char3).concat(socEnd).concat(ChargePredictFields.ins().char3).concat(String.valueOf(i));
            return concat;
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 更新计算
     * @param line
     * @return
     */
    private String calOfUpdateFirstIsNull(JSONObject line
            , MapState<String, String> timeOfLatest5State
            ,MapState<String, String> startSocState
            ,MapState<String, String> initState
    ) {
        try {
            line.put("policyType","update-jisuan-first_is_null");
            String chargeIdName = chargeIdName(line);
            //获取前5个点的充电时长
            float sliceTime = sliceTimeOfLatest5Record(line,timeOfLatest5State);
            if (sliceTime<=0){
                return null;
            }
            //END.结果计算
            Float bmsSocF = line.getFloat(ChargePredictFields.ins().srcFieldBmsSoc);
            int i = new BigDecimal(sliceTime*(100-bmsSocF)/60000).setScale( 0, BigDecimal.ROUND_HALF_DOWN).intValue();
            if (i>DwsStrConstant.ins().timeLim){
                System.out.println(String.format("chargeId=%s ,cal_first --->  time(%s) > 1000 ",chargeIdName(line),i));
                //起始点的充电时长不能太长
                i =DwsStrConstant.ins().timeLim;
            }
            String bmsSoc = line.getString(ChargePredictFields.ins().srcFieldBmsSoc);
            System.out.println(String.format("chargeId=%s,update_first_is_null ---> time=%s,bms_innersoc=%s,sliceTime=%s",chargeIdName,i,bmsSoc,sliceTime));
            String socEnd = line.getString(steadySocEndKey);
            if (StringUtils.isBlank(socEnd)){
                socEnd ="100";
            }
            String concat = bmsSoc.concat(ChargePredictFields.ins().char3).concat(socEnd).concat(ChargePredictFields.ins().char3).concat(String.valueOf(i));
            return concat;
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }
    private float getStartSocVal(JSONObject line, MapState<String, String> startSocState) {
        try {
            String chargeIdName = chargeIdName(line);
            String s = startSocState.get(chargeIdName);
            float startsoc = Float.parseFloat(s);
            return startsoc;
        }catch (Exception e){
            e.printStackTrace();
        }
        return 0;
    }

    /**
     *  涓流阶段时间计算
     * @param line
     * @param sliceTime
     * @return
     */
    private float stageOfTrickle(JSONObject line, float sliceTime,float startSocVal,MapState<String, String> initState) {
        try {
            boolean b = startSocVal > 80;
            if (b){
                //如果用户起点SOC过高，则可压缩的优先级首先为平台期、其次为涓流期。
                return 0;
            }
            //当前soc 是否处于涓流期阶段
            Float bmsSoc = line.getFloat(ChargePredictFields.ins().srcFieldBmsSoc);
            if (bmsSoc <= 80){
                //获取初始阶段匹配到的数据
                String chargeIdName = chargeIdName(line);
                String s = initState.get(chargeIdName.concat("timeOfTrickle"));
                if (StringUtils.isBlank(s)){
                    float v = new BigDecimal(sliceTime).multiply(new BigDecimal(20)).setScale(0, BigDecimal.ROUND_HALF_DOWN).floatValue();
                    System.out.println(String.format("chargeId=%s,soc=%s,stageOfEfficient  time( sliceTime*20 )---> %s = %s * 20 ",chargeIdName(line),bmsSoc,v,sliceTime));
                    s = String.valueOf(v);
                }
                float timeOfTrickle = Float.parseFloat(s);
                return timeOfTrickle;
            }
            //是涓流
            float deltaSoc = 100 - bmsSoc;
            float v = new BigDecimal(sliceTime).multiply(new BigDecimal(deltaSoc)).setScale(0, BigDecimal.ROUND_HALF_DOWN).floatValue();
            System.out.println(String.format("chargeId=%s,soc=%s,stageOfEfficient  time( sliceTime*(100 - bmsSoc) )---> %s = %s * (80 - %s) ",chargeIdName(line),bmsSoc,v,sliceTime,bmsSoc));
            return v;
        }catch (Exception e){
            e.printStackTrace();
        }
        return 0;
    }

    /**
     *  高效充电阶段时间计算
     * @param line
     * @param sliceTime
     * @return
     */
    private float stageOfEfficient(JSONObject line, float sliceTime,float startSocVal,MapState<String, String> initState) {
        try {
            Float bmsSoc = line.getFloat(ChargePredictFields.ins().srcFieldBmsSoc);
            if (startSocVal>80){
                //如果用户起点SOC过高，则可压缩的优先级首先为平台期、其次为涓流期。
                return 0;
            }
            //判断开始soc+10的位置
            float stageStart = startSocVal + 10;
            float stageEnd = 80;
            //当前是在修正期
            if (bmsSoc <= stageStart){
                //获取初始阶段匹配到的数据
                String idName = chargeIdName(line);
                String efficient = initState.get(idName.concat("timeOfEfficient"));
                if (StringUtils.isBlank(efficient)){
//                    float deltaSoc = 80 - bmsSoc;
                    float deltaSoc = 80 - stageStart;
                    long v = new BigDecimal(sliceTime).multiply(new BigDecimal(deltaSoc)).setScale(0, BigDecimal.ROUND_HALF_DOWN).longValue();
                    System.out.println(String.format("chargeId=%s,soc=%s,stageOfEfficient  time( sliceTime*(80 - stageStart) )---> %s = %s * (80 - %s) ",chargeIdName(line),bmsSoc,v,sliceTime,stageStart));
                    efficient = String.valueOf(v);
                }
                float timeOfEfficient = Float.parseFloat(efficient);
                //修正时间
                String timeOfRevise = initState.get(idName.concat("timeOfRevise"));
                if (StringUtils.isBlank(timeOfRevise)){
                    timeOfRevise = DwsStrConstant.ins().str0;
                }
                float t2 = Float.parseFloat(timeOfRevise);
                return timeOfEfficient + t2;
            }
            //当前soc 是否处于高效期阶段
            boolean b = bmsSoc > stageStart && bmsSoc<stageEnd && stageStart<stageEnd  ;
            if(!b){
                //不是高效期
                return 0;
            }
            //是高效期阶段
            float deltaSoc = 80 - bmsSoc;
            float v = new BigDecimal(sliceTime).multiply(new BigDecimal(deltaSoc)).setScale(0, BigDecimal.ROUND_HALF_DOWN).floatValue();
            System.out.println(String.format("chargeId=%s,soc=%s,stageOfEfficient  time( sliceTime*(80 - bmsSoc) )---> %s = %s * (80 - %s) ",chargeIdName(line),bmsSoc,v,sliceTime,bmsSoc));
            //修正时间
            String timeOfRevise = initState.get(chargeIdName(line).concat("timeOfRevise"));
            if (StringUtils.isBlank(timeOfRevise)){
                timeOfRevise = DwsStrConstant.ins().str0;
            }
            float t2 = Float.parseFloat(timeOfRevise);
            if (v<t2){
                return v;
            }
//            return v + t2;
            return v ;
        }catch (Exception e){
            e.printStackTrace();
        }
        return 0;
    }

    /**
     * 温度调节阶段时间计算
     * @param line
     * @param sliceTime
     * @return
     */
    private float stageOfTempAdjust(JSONObject line,float sliceTime,float startSocVal) {
        try {
            Float bmsSoc = line.getFloat(ChargePredictFields.ins().srcFieldBmsSoc);
            if (startSocVal>80){
                //如果用户七点soc过高，则可压缩的优先级首先为平台期、其次为涓流期
                long l = new BigDecimal((100 - bmsSoc) * sliceTime).setScale(1, BigDecimal.ROUND_HALF_UP).longValue();
                return l;
            }
            //startsoc+10 - 当前soc的差值，乘以充电时长 即调节阶段时间
            float stageEnd = startSocVal + 10;
            //如果stageEnd 大于 80
            boolean lt80 = stageEnd > 80;
            if (lt80){
                return 0;
            }
            //如果小于0 说明时间已过了这个阶段
            if (bmsSoc > stageEnd){
                //修正期已经结束
                return 0;
            }
            float deltaSoc = stageEnd - bmsSoc;
            long v = new BigDecimal(sliceTime).multiply(new BigDecimal(deltaSoc)).setScale(0, BigDecimal.ROUND_HALF_DOWN).longValue();
            System.out.println(String.format("chargeId=%s,soc=%s,stageOfTempAdjust  time( sliceTime*(stageEnd - bmsSoc) )---> %s = %s * (%s - %s) ",chargeIdName(line),bmsSoc,v,sliceTime,stageEnd,bmsSoc));
            return v;
        }catch (Exception e){
            e.printStackTrace();
        }
        return 0;
    }

    private float sliceTimeOfLatest5Record(JSONObject line,MapState<String, String> timeOfLatest5State) {
        if (true){
            //加权平均值
            return sliceTimeOfLatest5RecordV2(line,timeOfLatest5State);
            //算术平均值
//            return sliceTimeOfLatest5RecordV1(line,timeOfLatest5State);
        }
        try {
            String chargeIdName = chargeIdName(line);
            String s = timeOfLatest5State.get(chargeIdName);
            if (StringUtils.isBlank(s)){
                return 0;
            }
            String[] split = s.split(ChargePredictFields.ins().char3);
            //确保是有序的
            ArrayList<String> list = new ArrayList<>();
            for (int i = 0; i < split.length; i++) {
                list.add(split[i]);
            }
            Collections.sort(list);
            //
            float res = 0;
            Long tidVal = line.getLong(ChargePredictFields.ins().srcFieldTid);
            long startTime = Long.parseLong(list.get(0));
            long totalTime = tidVal - startTime;
            for (int i = 0; i < split.length; i++) {
                String tid1 = list.get(i);
                String tid2 = null;
                if(i == split.length -1){
                    tid2 = tidVal.toString();
                }else {
                    tid2 = list.get(i+1);
                }
                long l = Long.parseLong(tid2) - Long.parseLong(tid1);
                float v1 = (Float.parseFloat(String.valueOf(l)) / Float.parseFloat(String.valueOf(totalTime))) * Float.parseFloat(String.valueOf(l));
                float v2 = new BigDecimal(v1).setScale(1,BigDecimal.ROUND_HALF_UP).floatValue();
//                System.out.println(String.format("tid2=%s, tid1=%s, delta(l)=%s ,total=%s , l/total*l=%s ,v1=%s",tid2,tid1,l,totalTime,v2,v1))
                res += v2;
            }
            if (list.size()==0){
                res =0;
            }else {
                res = totalTime / Float.parseFloat(String.valueOf(list.size()));
            }
            System.out.println(String.format("chargeId=%s,latest_5_state ---> latest5Record=%s,item_time=%s,sliceTime=%s", chargeIdName, JSONObject.toJSONString(list),tidVal,res));
            return res;
        }catch (Exception e){
            e.printStackTrace();
        }
        return 0;
    }
    /*
       加权平均值
     */
    private float sliceTimeOfLatest5RecordV2(JSONObject line,MapState<String, String> timeOfLatest5State) {
        try {
            String chargeIdName = chargeIdName(line);
            String s = timeOfLatest5State.get(chargeIdName);
            if (StringUtils.isBlank(s)){
                return 0;
            }
            String[] split = s.split(ChargePredictFields.ins().char3);
            ArrayList<String> list = new ArrayList<>();
            for (int i = 0; i < split.length; i++) {
                list.add(split[i]);
            }
            //确保是有序的
            Collections.sort(list);
            //获取当前记录时间
            Long tid = line.getLong(ChargePredictFields.ins().srcFieldTid);
            String firstTid = list.get(0).split(ChargePredictFields.ins().colon)[0];
            long totalTime = tid - Long.parseLong(firstTid);
            float cnt = 0;
            list.add(tid.toString());
            String aa = "";
            for (int i = 1; i < list.size(); i++){
                int lastI = i -1;

                String item = list.get(i);
                String[] itemSp = item.split(ChargePredictFields.ins().colon);
                String itemTidStr = itemSp[0];

                String lastItem = list.get(lastI);
                String[] lastItemSp = lastItem.split(ChargePredictFields.ins().colon);
                String lastItemTidStr = lastItemSp[0];
                long sliceTime = Long.parseLong(itemTidStr) - Long.parseLong(lastItemTidStr);

                //计算权重
                float v = new BigDecimal(sliceTime ).divide(new BigDecimal(totalTime),5,BigDecimal.ROUND_HALF_UP).floatValue();
                //计算加权平均值
                float f = new BigDecimal(sliceTime * v ).setScale(1, BigDecimal.ROUND_HALF_UP).floatValue();
                cnt +=f;
                aa=aa.concat(tid.toString()).concat(ChargePredictFields.ins().colon).concat(String.valueOf(v))
                        .concat(ChargePredictFields.ins().colon).concat(String.valueOf(f))
                        .concat(ChargePredictFields.ins().char3)
                ;
            }
            Float soc = line.getFloat(ChargePredictFields.ins().srcFieldBmsSoc);
            float v= cnt*0.95f;
//            if (soc>=90){
//                v = cnt*0.9f;
//            }else if (soc>=20){
//                v = cnt*0.95f;
//            }else {
//                v= cnt*1.0f;
//            }
            System.out.println(String.format("chargeId=%s,latest_5_state ---> latest5Record=%s,res=%s,sliceTime=%s", chargeIdName, aa,cnt,v));
            return v;
        }catch (Exception e){
            e.printStackTrace();
        }
        return 0;
    }
    /*
        算术平均值
     */
    private float sliceTimeOfLatest5RecordV1(JSONObject line,MapState<String, String> timeOfLatest5State) {
        try {
            String chargeIdName = chargeIdName(line);
            String s = timeOfLatest5State.get(chargeIdName);
            if (StringUtils.isBlank(s)){
                return 0;
            }
            String[] split = s.split(ChargePredictFields.ins().char3);
            //确保是有序的
            ArrayList<String> list = new ArrayList<>();
            for (int i = 0; i < split.length; i++) {
                list.add(split[i]);
            }
            Collections.sort(list);
            Long tidVal = line.getLong(ChargePredictFields.ins().srcFieldTid);
            long startTime = Long.parseLong(list.get(0).split(ChargePredictFields.ins().colon)[0]);
            long totalTime = tidVal - startTime;
            float totalF = Float.parseFloat(String.valueOf(totalTime));
            int r = 1;
            if(DwsStrConstant.ins().socInt==10){
                r = 2;
            }
            float v = new BigDecimal(totalF*r / list.size() ).setScale(1, BigDecimal.ROUND_HALF_UP).floatValue();
            System.out.println(String.format("chargeId=%s,latest_5_state ---> latest5Record=%s,item_time=%s,sliceTime=%s", chargeIdName, JSONObject.toJSONString(list),tidVal,v));
            Float soc = line.getFloat(ChargePredictFields.ins().srcFieldBmsSoc);
            if (soc>=90){
                return v*0.9f;
            }else if (soc>=20){
                return v*0.95f;
            }
//            v= v*0.9f;
            return v;
        }catch (Exception e){
            e.printStackTrace();
        }
        return 0;
    }
    /**
     * 初始计算
     * @param line
     * @return
     */
    private String calOfFirst(JSONObject line,MapState<String, String> initState) {
        try {
            //初始计算 当前工况 - vin poiid 温度 电流 电压 soc
            String bmsSoc = line.getString(ChargePredictFields.ins().srcFieldBmsSoc);
            //构建sql语句
            String whereAfterStr = queryOption(line,false);
//            String fromStrLocal = String.format(fromStr, "dws_charge_detail_slice");
            String fromStrLocal = String.format(fromStr, "dws_charge_detail_slice_dcobc");
            String dc = line.getString(ChargePredictFields.ins().srcFieldBmsDcConnect);
            if (StringUtils.equalsIgnoreCase(dc,DwsStrConstant.ins().str1)){
//                fromStrLocal = String.format(fromStr, "dws_charge_detail_slice_dc");
                fromStrLocal = String.format(fromStr, "dws_charge_detail_slice_dcobc");
            }
            String select = poiSelect(selectStr,line);
            String sqlStr = String.format(select,bmsSoc,bmsSoc).concat(fromStrLocal).concat(whereAfterStr);
            long t0 = System.currentTimeMillis();
            List<JSONObject> list = queryExecution(sqlStr,line);
            System.out.println(String.format(" chargeId=%s , deviceid cost time ==> %s ms ",chargeIdName(line),System.currentTimeMillis() - t0));
            //2.基于上一步结果匹配电流、地点维度
            JSONObject json= poiIdDimension(line,list);
            if (json==null){
                //先用经验值
                long t1 = System.currentTimeMillis();
                String process = cloudDefaultVal.process(line);
                System.out.println(String.format("chargeId=%s ,  default  jingyanzhi cost time ==> %s ms ",chargeIdName(line),System.currentTimeMillis() - t1));
                if (StringUtils.isNotBlank(process)){
                    line.put("policyType","beginning-modelcode");
                    return  process;
                }
                else {return "0#0#-999999";}
//                //没有匹配成功再用modelcode匹配
//                long startTime1 = System.currentTimeMillis();
//                json = defaultMatch(line);
//                System.out.println(String.format("chargeId=%s ,  model_code cost time ==> %s ms ",chargeIdName(line),System.currentTimeMillis() - startTime1));
//                if (json == null){
//                    //调用更新策略
//                    return null;
//                }
//                line.put("policyType","beginning-modelcode");
            }
            line.put("policyType","beginning-jisuan");
            //匹配成功
            System.out.println(String.format("chargeId=%s ,sample ---> %s",chargeIdName(line),json.toJSONString()));
            //3.前端修正时长 修订计算
            float timeOfRevise = reviseOfStart(json,line);
            //分段：温度调节时间 高效充电 涓流充电
            infoOfSample2State(json,line,initState,timeOfRevise);
            //END.结果计算
            Long effectiveTime = json.getLong(effectiveChargeTimeKey);
            float l = effectiveTime + timeOfRevise /1000;
            int i = new BigDecimal(l).divide(new BigDecimal(60), 0, BigDecimal.ROUND_HALF_DOWN).intValue();
            if (i>1000){
                //起始点的充电时长不能太长
                i =1000;
                System.out.println(String.format("chargeId=%s ,cal_first --->  time > 1000 ",chargeIdName(line)));
            }
            String socEnd = json.getString(steadySocEndKey);
            if (StringUtils.isBlank(socEnd)){
                socEnd ="100";
            }
            String concat = bmsSoc.concat(ChargePredictFields.ins().char3).concat(socEnd).concat(ChargePredictFields.ins().char3).concat(String.valueOf(i));
            System.out.println(String.format("chargeId=%s ,cal_first --->  time=%s ,effectivechargetime + timeOfRevise/1000 =%s,%s",chargeIdName(line),concat,effectiveTime,timeOfRevise/1000));
            return concat;
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

    private String poiSelect(String selectStr, JSONObject line) {
        String poiId = line.getString(ChargePredictFields.ins().srcFieldPoiId);
        String aoiId = line.getString(ChargePredictFields.ins().srcFieldAoiId);
        //这个条件可能有也可能没有,有如下四种情况
        //1 poi=-9  aoi = -9 则没有这个条件
        //2 poi=-9  aoi = A  则条件是 aoi=A
        //3 poi=A   aoi = -9 则条件是 poi=A
        //4 poi=A   aoi = A 则条件是 poi=A || aoi=A
        boolean poiB =  StringUtils.isBlank(poiId) || StringUtils.equalsIgnoreCase(poiId, ChargePredictFields.ins().defaultVal);

        boolean aoiB = StringUtils.isBlank(aoiId) || StringUtils.equalsIgnoreCase(aoiId, ChargePredictFields.ins().defaultVal);
        String res = selectStr;
        if (poiB){
            // poi = -9 或者 空
            if (aoiB){
                //没有这个条件
                res = selectStr.concat(" , \"aoiid\" =\'-9\' as \"poiDim\" ");
            }else {
                //条件是 aoi =A
                res = selectStr.concat(" , \"aoiid\" =\'").concat(aoiId).concat("\' as \"poiDim\" ");
            }
        }else {
            // poi = A
            if (aoiB){
                //条件是 poi = A
                res = selectStr.concat(" , \"poiid\" =\'").concat(poiId).concat("\' as \"poiDim\" ");
            }else {
                //条件是 poi=A || aoi=A
                res = selectStr.concat(" , ( \"poiid\" =\'").concat(poiId).concat("\' or \"aoiid\"=\'").concat(aoiId).concat("\' ) as \"poiDim\" ");
            }
        }
        return res;
    }

    /**
     *  将匹配到的样本进行存储 便于更新阶段读取
     * @param json
     * @param line
     * @param initState
     */
    private void infoOfSample2State(JSONObject json, JSONObject line, MapState<String, String> initState, float timeOfRevise) {
        if (initState==null){
            return;
        }
        String chargeId = chargeIdName(line);
        try {
            //修正时间
            String key1 = chargeId.concat("timeOfRevise");
            initState.put(key1,String.valueOf(timeOfRevise));
            //高效时间
            Long time10 = json.getLong(steadyTime10Key);
            Long time80 = json.getLong(steadyTime80Key);
            Long time100 = json.getLong(steadyTimeEndKey);

            long l = time80 - time10;
            String key2 = chargeId.concat("timeOfEfficient");
            initState.put(key2,String.valueOf(l));
            //涓流时间
            long lg = time100 - time80;
            String key3 = chargeId.concat("timeOfTrickle");
            initState.put(key3,String.valueOf(lg));
            System.out.println(String.format("chargeId=%s ,info_of_stages(cal_first) ---> timeOfRevise=%s ,timeOfEfficient=%s ,timeOfTrickle=%s",chargeId,timeOfRevise,l,lg));
        }catch (Exception e){
            e.printStackTrace();
            System.out.println(String.format("exception:%s, chargeId=%s ", ExceptionUtils.getMessage(e),chargeId));
        }
    }

    private String chargeIdName(JSONObject line){
        String vin = line.getString(ChargePredictFields.ins().srcFieldVin);
        String startChargeTime = line.getString(ChargePredictFields.ins().srcFieldStartChargeTime);
        String chargeId = vin.concat(startChargeTime);
        return chargeId;
    }
    private JSONObject defaultMatch(JSONObject line) {
        //初始计算 如果提取不到对应的记录，以CC码为单位，提取时间最近、差异最小的记录；
        //构建sql语句
        String whereAfterStr = queryOptionModel(line,false);
        Float bmsSoc = line.getFloat(ChargePredictFields.ins().srcFieldBmsSoc);

//        String fromStrModelLocal = String.format(fromStrModel, "dws_charge_detail_slice");
        String fromStrModelLocal = String.format(fromStrModel, "dws_charge_detail_slice_dcobc");
        String dc = line.getString(ChargePredictFields.ins().srcFieldBmsDcConnect);
        if (StringUtils.equalsIgnoreCase(dc,DwsStrConstant.ins().str1)){
//            fromStrModelLocal = String.format(fromStrModel, "dws_charge_detail_slice_dc");
            fromStrModelLocal = String.format(fromStrModel, "dws_charge_detail_slice_dcobc");
        }
        String select = poiSelect(selectStr,line);
        String sqlStr = String.format(select, bmsSoc, bmsSoc).concat(fromStrModelLocal).concat(whereAfterStr);
        List<JSONObject> list = queryExecution(sqlStr,line);
        //2.基于上一步结果匹配电流、地点维度
        JSONObject json= poiIdDimension(line,list);
        if (json==null){
            //去掉 地点维度 再匹配一次  [高度优先本地点的充电记录]
//            whereAfterStr = queryOptionModel(line,false);
//            sqlStr = String.format(selectStr, bmsSoc, bmsSoc).concat(fromStrModelLocal).concat(whereAfterStr);
//            list = queryExecution(sqlStr,line);
//            json= poiIdDimension(line,list);
        }
        return json;
    }

    /**
     *
     * 前端修正时间
     * @param json
     * @param line
     * @return
     */
    private float reviseOfStart(JSONObject json, JSONObject line) {
        //计算起点SOC和参考样本的SOC差的绝对值，参考样本数据SOC充满此差值的时间t2，作为充电时长修订量
        Float innerSocLine = line.getFloat(ChargePredictFields.ins().srcFieldBmsSoc);
        Float innerSocSlice = json.getFloat(innerSocKey);
        BigDecimal bigDecimal = json.getBigDecimal(sliceTimeKey);
        float deltaSoc = innerSocSlice - innerSocLine;

        Float socEnd = json.getFloat(steadySocEndKey);
        Float effectiveTime = json.getFloat(effectiveChargeTimeKey);
        Float startSoc = json.getFloat(startSocKey);
        float v = effectiveTime / (socEnd - startSoc);
        float res = new BigDecimal(v).setScale(1, BigDecimal.ROUND_HALF_UP).floatValue();
//        return res*deltaSoc;
        Long sliceTime = bigDecimal.longValueExact();
        return  (sliceTime*deltaSoc);
    }

    private String queryOption(JSONObject line,boolean hasPoiDim){
        //获取当前工况
        String vin = line.getString(ChargePredictFields.ins().srcFieldVin);
        Long tidVal = line.getLong(ChargePredictFields.ins().srcFieldTid);
        String startChargeTime = line.getString(ChargePredictFields.ins().srcFieldStartChargeTime);
        String poiId = line.getString(ChargePredictFields.ins().srcFieldPoiId);
        String aoiId = line.getString(ChargePredictFields.ins().srcFieldAoiId);
        String tempMin = line.getString(ChargePredictFields.ins().srcFieldBmsRmcModuleTempMin);
        String tempMax = line.getString(ChargePredictFields.ins().srcFieldBmsRmcModuleTempMax);
        Float bmsCurr = line.getFloat(ChargePredictFields.ins().srcFieldBmsBatterCurrRm);
        String voltMax = line.getString(ChargePredictFields.ins().srcFieldVoltMax);
        Float bmsSoc = line.getFloat(ChargePredictFields.ins().srcFieldBmsSoc);
        String modelCode = line.getString(ChargePredictFields.ins().srcFieldModelCode);
        String acOpen = line.getString(ChargePredictFields.ins().srcFieldAcOpen);
        String heat = line.getString(ChargePredictFields.ins().srcFieldBmsHeatReq);
        String cool = line.getString(ChargePredictFields.ins().srcFieldBmsCoolReq);
        String obc = line.getString(ChargePredictFields.ins().srcFieldBmsObcConnect);
        String dc = line.getString(ChargePredictFields.ins().srcFieldBmsDcConnect);
        //车辆vin、地点、电流、起点soc、电池温度、目标soc、加热、空调开启
        StringBuilder stringBuilder = new StringBuilder();
        dimension.rnDimStr(stringBuilder,modelCode);
        dimension.andOps(stringBuilder);
        dimension.startSocDim(stringBuilder,bmsSoc);
        dimension.andOps(stringBuilder);

        dimension.deviceIdDim(stringBuilder,vin,true);
        dimension.andOps(stringBuilder);
        boolean firstTime = line.getBooleanValue(ChargePredictFields.ins().firstTimeField);
        dimension.startTimeDim(stringBuilder,startChargeTime,firstTime);
        dimension.andOps(stringBuilder);
        dimension.socDim(stringBuilder,bmsSoc);
        //startsoc
        dimension.andOps(stringBuilder);
        dimension.tempDim(stringBuilder,tempMin);
        dimension.andOps(stringBuilder);
//        dimension.currDimObc(stringBuilder,bmsCurr,voltMax);
        dimension.currDimObc2(stringBuilder,bmsCurr,voltMax);
        dimension.andOps(stringBuilder);
        dimension.steadyTimeDim(stringBuilder);
        dimension.andOps(stringBuilder);
        dimension.dcObcDim(stringBuilder,obc,dc);
        if (hasPoiDim){
            dimension.poiDim(stringBuilder,poiId,aoiId);
        }
        dimension.orderByObc(stringBuilder);
        //拼接
        return stringBuilder.toString();
    }
    private String queryOptionModel(JSONObject line,boolean hasPoiDim){
        //获取当前工况
        String vin = line.getString(ChargePredictFields.ins().srcFieldVin);
        Long tidVal = line.getLong(ChargePredictFields.ins().srcFieldTid);
        String startChargeTime = line.getString(ChargePredictFields.ins().srcFieldStartChargeTime);
        String poiId = line.getString(ChargePredictFields.ins().srcFieldPoiId);
        String aoiId = line.getString(ChargePredictFields.ins().srcFieldAoiId);
        String tempMin = line.getString(ChargePredictFields.ins().srcFieldBmsRmcModuleTempMin);
        String tempMax = line.getString(ChargePredictFields.ins().srcFieldBmsRmcModuleTempMax);
        Float bmsCurr = line.getFloat(ChargePredictFields.ins().srcFieldBmsBatterCurrRm);
        String voltMax = line.getString(ChargePredictFields.ins().srcFieldVoltMax);
        Float bmsSoc = line.getFloat(ChargePredictFields.ins().srcFieldBmsSoc);
        String modelCode = line.getString(ChargePredictFields.ins().srcFieldModelCode);
        String acOpen = line.getString(ChargePredictFields.ins().srcFieldAcOpen);
        String heat = line.getString(ChargePredictFields.ins().srcFieldBmsHeatReq);
        String cool = line.getString(ChargePredictFields.ins().srcFieldBmsCoolReq);
        String obc = line.getString(ChargePredictFields.ins().srcFieldBmsObcConnect);
        String dc = line.getString(ChargePredictFields.ins().srcFieldBmsDcConnect);
        //车辆vin、地点、电流、起点soc、电池温度、目标soc、加热、空调开启
        StringBuilder stringBuilder = new StringBuilder();
        dimension.rnDimStr(stringBuilder,modelCode);
        dimension.andOps(stringBuilder);
        dimension.startSocDim(stringBuilder,bmsSoc);
        dimension.andOps(stringBuilder);

        dimension.modelDim(stringBuilder,modelCode);
        dimension.andOps(stringBuilder);

        //startsoc
        dimension.socDim(stringBuilder,bmsSoc);
        dimension.andOps(stringBuilder);
        dimension.tempDim(stringBuilder,tempMin);
        dimension.andOps(stringBuilder);
//        dimension.currDimObc(stringBuilder,bmsCurr,voltMax);
        dimension.currDimObc2(stringBuilder,bmsCurr,voltMax);
        boolean firstTime = line.getBooleanValue(ChargePredictFields.ins().firstTimeField);
        dimension.andOps(stringBuilder);
        dimension.startTimeDim(stringBuilder,startChargeTime,firstTime);
        dimension.andOps(stringBuilder);
        dimension.steadyTimeDim(stringBuilder);
        dimension.andOps(stringBuilder);
        dimension.dcObcDim(stringBuilder,obc,dc);
        if (hasPoiDim){
            dimension.poiDim(stringBuilder,poiId,aoiId);    
        }
        dimension.orderByObcDefault(stringBuilder);
        //拼接
        return stringBuilder.toString();
    }
    private String selectStr = "select regexp_split(id,\'-\')[1] as \"deviceid\",reverse(regexp_split(id,\'-\')[2]) as \"item_time\",\"bms_innersoc\",\"startchargetime\",\"bms_rmc_moduletempmin\",\"totaltime\",\"model_code\",\"bms_battcurr_rm\",\"steady_soc_10\",\"steady_time_10\",\"steady_soc_80\",\"steady_time_80\",\"poiid\",\"aoiid\",\"endchargetime\",\"end_bms_innersoc\",\"effectivechargetime\",\"startsoc\" ,abs(to_number(\"startsoc\")- %s) as \"deltaSocAbs\",(to_number(\"startsoc\")- %s) as \"deltaSoc\" ";
    private String fromStr =" from \"vaas_dws\".\"%s\"  where ";
    private String fromStrModel =" from \"vaas_dws\".\"%s\"  where ";
    private CloudMatchDimension dimension = new CloudMatchDimension();

    private List<JSONObject> queryExecution(String sqlStr,JSONObject line) {
        //查一个曲线的开始点 一条曲线只需要查找开始点，之后根据开始点查找结束点，这样就是一条曲线
        Connection connection = null;
        ArrayList<JSONObject> list = new ArrayList<>();
        try {
            String sql = sqlStr;
            String soc = line.getString(ChargePredictFields.ins().srcFieldBmsSoc);
            System.out.println(String.format("chargeId=%s ,soc=%s,sql_of_match ---> %s ",chargeIdName(line),soc,sql));
            connection = HBaseDataSource.ins().getConnection();
            PreparedStatement preparedStatement = connection.prepareStatement(sql);
            ResultSet rs = null;
            try {
                rs = preparedStatement.executeQuery();
            }catch (Exception e){
                //第一次如果报错了，那么就重试一次，如果还是错误先跳过
                rs = preparedStatement.executeQuery();
            }
            HashSet<String> uniqSet = new HashSet<>();
            while (rs.next()) {
                String deviceId = rs.getString(1);
                //如果deviceid是空，
                if (StringUtils.isBlank(deviceId)){
                    continue;
                }
                String itemTime = rs.getString(2);
                String bmsInnersoc = rs.getString(3);
                String startchargetime = rs.getString(4);
                String uniqKey = deviceId.concat(startchargetime);
                //保留:一个deviceid 一次充电记录 保留一个
                if(uniqSet.contains(uniqKey)){
                    continue;
                }
                uniqSet.add(uniqKey);
                String bmsRmcModuletempmin = rs.getString(5);
                String e = rs.getString(6);
                if (e==null || StringUtils.isBlank(e)){continue;}
                String modelCode = rs.getString(7);
                String bmsBattcurrRm = rs.getString(8);
                String steadySoc10 = rs.getString(9);

                String steadyTime10 = rs.getString(10);
                String steadySoc80 = rs.getString(11);
                String steadyTime80 = rs.getString(12);
                if(StringUtils.isBlank(steadyTime10) || StringUtils.isBlank(steadyTime80)){
                    continue;
                }
                String poiid = rs.getString(13);
                String aoiid = rs.getString(14);
                String steadyTimeEnd = rs.getString(15);
                String steadySocEnd = rs.getString(16);
                String effectiveChargeTime = rs.getString(17);
                String startsoc = rs.getString(18);
                JSONObject json = new JSONObject();
                json.put(deviceIdKey,deviceId);
                json.put(itemTimeKey,itemTime);
                json.put(innerSocKey,bmsInnersoc);
                json.put(startChargeTimeKey,startchargetime);
                json.put(acAmbKey,bmsRmcModuletempmin);
                json.put(sliceTimeKey,e);
                json.put(modelCodeKey,modelCode);
                json.put(currKey,bmsBattcurrRm);
                json.put(steadySoc10Key,steadySoc10);
                json.put(steadyTime10Key,steadyTime10);
                json.put(steadySoc80Key,steadySoc80);
                json.put(steadyTime80Key,steadyTime80);
                json.put(poiidKey,poiid);
                json.put(aoiidKey,aoiid);
                json.put(steadySocEndKey,steadySocEnd);
                json.put(steadyTimeEndKey,steadyTimeEnd);
                json.put(effectiveChargeTimeKey,effectiveChargeTime);
                json.put(startSocKey,startsoc);
                list.add(json);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            HBaseDataSource.ins().close(connection);
        }
        return list;
    }

    /**
     * 地点维度
     * @param line
     * @param list
     * @return
     */
    private JSONObject poiIdDimension(JSONObject line,List<JSONObject> list) {
        //将同一个地点 同一个vin 电流相同的记录找出
        if (list==null || list.size()==0){
            return null;
        }
        JSONObject jsonObject = list.get(0);
        return jsonObject;
    }
    private String deviceIdKey = "deviceId";
    private String itemTimeKey = "item_time";
    private String innerSocKey = "bms_innersoc";
    private String startChargeTimeKey = "startChargeTime";
    private String acAmbKey = "bms_rmc_moduletempmin";
    private String sliceTimeKey = "totaltime";
    private String modelCodeKey = "model_code";
    private String currKey = "bms_battcurr_rm";
    private String steadySoc10Key = "steady_soc_10";
    private String steadyTime10Key = "steady_time_10";
    private String steadySoc80Key = "steady_soc_80";
    private String steadyTime80Key = "steady_time_80";
    private String poiidKey = "poiid";
    private String aoiidKey = "aoiid";
    private String steadySocEndKey = "end_bms_innersoc";
    private String steadyTimeEndKey = "endchargetime";
    private String effectiveChargeTimeKey = "effectivechargetime";
    private String startSocKey = "startsoc";

}
